/*
    测试三要素：
        1. 测试环境
        2. 测试方法
        3. 测试结果
*/

#include <thread>
#include <vector>
#include "../logs/bitlog.h"

// 日志器名称，线程数量，总日志数量，总日志长度
void bench(const std::string &logger_name, size_t thr_count, size_t msg_count, size_t msg_len)
{
    // 1. 获取日志器
    Log::Logger::ptr logger = Log::getLogger(logger_name);
    if (logger.get() == nullptr)
        return;

    std::cout << "测试日志: " << msg_count << " 条，总大小: " << (msg_count * msg_len) / 1024 << "KB\n";
    // 2. 组织指定长度的日志消息
    std::string msg(msg_len - 1, 'A'); // 少一个字节，是为了给末尾添加换行

    // 3. 创建指定数量的线程
    std::vector<std::thread> threads;
    std::vector<double> cost_array(thr_count);
    size_t msg_ptr_thr = msg_count / thr_count; // 每个线程要输出的日志数量
    for (int i = 0; i < thr_count; i++)
    {
        threads.emplace_back([&, i]()
                            {
                                // 4. 线程函数内部开始计时
                                std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
                                // 5. 开始循环写日志
                                for (int j = 0; j < msg_ptr_thr; j++)
                                {
                                    logger->FATAL("%s", msg.c_str());
                                }
                                // 6. 线程函数内部结束计时
                                std::chrono::high_resolution_clock::time_point end = std::chrono::high_resolution_clock::now();
                                std::chrono::duration<double> cost = end - start;
                                cost_array[i] = cost.count();
                                std::cout << "线程" << i << ": " << "\t输出数量: " << msg_ptr_thr << ", 耗时: " << cost.count() << std::endl;
                            });
    }
    for(int i = 0;i < thr_count;i++)
        threads[i].join();

    // 7. 计算总耗时: 在多线程中，每个线程都会耗费时间，但是线程是并发处理的，因此耗时最高的那个便是总时长
    double max_cost = cost_array[0];
    for(int i = 0;i < thr_count;i++)
        max_cost = max_cost < cost_array[i]?cost_array[i]:max_cost;

    size_t msg_per_sec = msg_count / max_cost;                          // 每秒输出日志数量
    size_t size_per_sec = (msg_count * msg_len) / (max_cost * 1024);    // 每秒输出日志大小

    // 8. 进行输出打印
    std::cout << "\t总耗时: " << max_cost << "s\n";
    std::cout << "\t每秒输出日志数量: " << msg_per_sec << "条\n";
    std::cout << "\t每秒输出日志大小: " << size_per_sec << "KB\n";
}

void sync_bench()
{
    std::unique_ptr<Log::LoggerBuild> builder(new Log::GlobalLoggerBuild());
    builder->BuildLoggerName("sync_logger");
    builder->BuildLoggerType(Log::LoggerType::LOGGER_SYNC);
    builder->BuildFormatter("%m%n");
    builder->BuildLogSink<Log::FileSink>("./LogFile/sync.log");
    builder->Build();
    bench("sync_logger",10,1000000,100);
}

void async_bench()
{
    std::unique_ptr<Log::LoggerBuild> builder(new Log::GlobalLoggerBuild());
    builder->BuildLoggerName("async_logger");
    builder->BuildLoggerType(Log::LoggerType::LOGGER_ASYNC);
    builder->BuildFormatter("%m%n");
    builder->BuildLogSink<Log::FileSink>("./LogFile/async.log");
    builder->Build();
    bench("async_logger",10,1000000,100);
}

int main()
{
    // sync_bench();
    async_bench();

    return 0;
}